package cat.joronya.supermanager.service;

import java.io.ByteArrayOutputStream;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.util.Log;
import cat.joronya.supermanager.Supermanager;

/**
 * AsyncTask on fem el login i parsejem les dades de la pagina
 * principal.
 * 
 * @author pol
 */
public class LoginSync extends Object//AsyncTask<String,Void,Integer>
{
	private static final String TAG = "supermanager";
	
	// el service
	private SupermanagerService service;
	
	// el client http on fer les peticions
	private DefaultHttpClient client = null;
	
	// login POST
	private static final String LOGIN_POST = InitSync.BASE_URL+"/index.php";
	
	// dades extretes de les pagines
	public String jornada = null;
	public String nextJornada = null;
	public Timestamp duetime = null;
	public String homeInfo = null;
	public int status = -1;
	
	/**
	 * Constructor amb el intentService que el crida.
	 * @param intentService
	 */
	public LoginSync(SupermanagerService service, DefaultHttpClient client)
	{
		this.service = service;
		this.client = client;
	}
	
	protected void execute(String username, String password) 
	{
		try
		{
			// checkejem per connectivitat
			ConnectivityManager cm = (ConnectivityManager) service.getSystemService(Context.CONNECTIVITY_SERVICE);
			boolean online = cm.getActiveNetworkInfo().isConnectedOrConnecting();
			
			if( !online )
				throw new ConnectivityException();
			
			// POST: login
			HttpPost loginHttpPost = new HttpPost(LOGIN_POST);
			
			String trimedUsername = username;
			if( username.length() > 25 )
				trimedUsername = username.substring(0, 25);
			String trimedPassword = password;
			if( password.length() > 8 )
				trimedPassword = password.substring(0, 8);
			
	        List <NameValuePair> nvps = new ArrayList <NameValuePair>();
	        nvps.add(new BasicNameValuePair("usuario", trimedUsername));
	        nvps.add(new BasicNameValuePair("clave", trimedPassword));
	        nvps.add(new BasicNameValuePair("control", "1"));

	        loginHttpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.ISO_8859_1));
	        HttpResponse response = client.execute(loginHttpPost);

	        ByteArrayOutputStream os = new ByteArrayOutputStream();
	        response.getEntity().writeTo(os);
	        String loginPage = os.toString(HTTP.ISO_8859_1);
	        
	        //LoginParser loginParser = LoginParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.jsoupImpl"));
	        //LoginParser loginParser = LoginParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.htmlcleanerImpl"));
	        LoginParser loginParser = LoginParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.substrImpl"));
	        Log.d(Supermanager.TAG, "Start parsing login page...");
	        long elapsedTime = loginParser.parse(loginPage);
	        Log.d(Supermanager.TAG, "Stop parsing login page! Elapsed time: "+elapsedTime/1000);
	        
	        jornada = loginParser.getJornada();
	        nextJornada = loginParser.getNextJornada();
	        duetime = loginParser.getDuetime();
	        homeInfo = loginParser.getHomeInfo();
	        status = loginParser.getStatus();
	        
	        if( status == Supermanager.CLOSED_STATUS || status == Supermanager.OPEN_NO_CHANGES_STATUS || 
	        		status == Supermanager.OTHER_ERROR_STATUS)
	        {
	        	nextJornada = jornada;
	        }
	        
	    }
		catch(ConnectivityException ce){
			status = Supermanager.CONNECTIVITY_ERROR_STATUS;
			return;
		}
		/*catch(AuthenticationException ae){
			// error d'autenticacio
			status = Supermanager.AUTH_ERROR_STATUS;
			return;
		}
		catch(ClosedWebException cwe){
			status = Supermanager.CLOSED_STATUS;
			nextJornada = jornada;
			return;
		}
		catch(ClosedChangesException cce){
			status = Supermanager.OPEN_NO_CHANGES_STATUS;
			nextJornada = jornada;
			return;
		}*/
		catch(Exception e){
			// altre error, notifiquem i anem offline
			status = Supermanager.OTHER_ERROR_STATUS;
			nextJornada = jornada;
			return;
		}

		// si ens hem connectat marquem que estem online
		//status = Supermanager.OPEN_STATUS;
    }

	/**
	 * Guardar les dades trobades a DB.
	 */
    protected void onPostExecute(Uri uri) 
    {
    	// si no esta web tancada i tenim jornada updatem
    	if( this.jornada != null )
    		insertOrUpdateHomeInfo(uri);
    	else
    		updateLastDayStatus(uri);
    	
    	// cal reprogramar l'alarma de notificacio de canvis
    	scheduleClosedChangesNotification();
    }
    
    private String updateLastDayStatus(Uri uri)
    {
    	Cursor lastDay = service.getContentResolver().query(Supermanager.Home.CONTENT_URI, 
    			new String[]{ Supermanager.Home._ID }, 
    			null, 
    			null, 
    			Supermanager.Home.DEFAULT_SORT_ORDER);
    	
    	Uri homeUri = Supermanager.Home.CONTENT_URI;
		String lastPathSegment = "0";
		
    	if( lastDay.moveToFirst() )
    	{
    		int id = lastDay.getInt(0);
    		ContentValues values = new ContentValues();
    		values.put(Supermanager.Home.STATUS, this.status);
    		
    		homeUri = ContentUris.withAppendedId(Supermanager.Home.CONTENT_URI, id);
    		service.getContentResolver().update(homeUri, 
    				values, 
    				null, 
    				null);
    		lastPathSegment = homeUri.getLastPathSegment();
			Log.d(TAG, "Updating home info to status "+ this.status
					+" for last day with Uri [" + homeUri + "] lastPathSegment ["
					+ lastPathSegment + "]");
    	}
    	else
    	{
    		// no tenim dia inicial, retornem error.
    		Log.e(TAG, "Error, no tenim cap dia i no podem updatar estat a tancat per canvis");
    	}
    	
    	return lastPathSegment;
    }
    
    private String insertOrUpdateHomeInfo(Uri uri)
	{
    	// insertem home info
		ContentValues values = new ContentValues();
		values.put(Supermanager.Home.DAY, this.jornada);
		values.put(Supermanager.Home.NEXT_DAY, this.nextJornada);
		values.put(Supermanager.Home.STATUS, this.status);
		values.put(Supermanager.Home.INFO, this.homeInfo);
		if( this.duetime != null )
			values.put(Supermanager.Home.DUE_TIME, (this.duetime.getTime()/1000));
		else
			values.put(Supermanager.Home.DUE_TIME, (String)null);
		
		Uri homeUri = Supermanager.Home.CONTENT_URI;
		String lastPathSegment = "0";
		
		// si update no retorna 1 reg, llavors insert
		if( service.getContentResolver().update(uri, 
				values, 
				Supermanager.Home.DAY+" = ? ", 
				new String[]{this.jornada}) == 0 )
		{
			homeUri = service.getContentResolver().insert(uri, values);
			lastPathSegment = homeUri.getLastPathSegment();
			Log.d(TAG, "Inserting home info for day [" + this.jornada
					+ "] with Uri [" + homeUri + "] lastPathSegment ["
					+ lastPathSegment + "]");
		}
		else
		{
			Cursor cursor = service.getContentResolver().
				query(Supermanager.Home.CONTENT_URI, 
					  Supermanager.Home.PROJECTION, 
					  Supermanager.Home.DAY+" = ? ", 
					  new String[]{this.jornada}, 
					  Supermanager.Home.DEFAULT_SORT_ORDER);
			
			if( cursor.moveToFirst() )
			{
				lastPathSegment = ""+cursor.getLong(0);
				homeUri = ContentUris.withAppendedId(Supermanager.Home.CONTENT_URI, cursor.getLong(0));
			}
			Log.d(TAG, "Updating home info for day [" +  this.jornada
					+ "] with Uri [" + homeUri + "] lastPathSegment ["
					+ lastPathSegment + "]");
		}
		
		return lastPathSegment;
	}
    
	/**
	 * Check if close changes notify is needed, and if so, do it.
	 * @param settings
	 */
	private void scheduleClosedChangesNotification()
	{
		SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this.service);
		
		// cron update?
		if( !settings.getBoolean(Supermanager.PREFS_DUETIME_NOTIFICATION_ENABLED, true) )
		{
			Log.d(TAG, "LoginSync: duetime notification not enabled, exiting.");
			return;
		}

		AlarmManager alarmManager = (AlarmManager)service.getSystemService(Context.ALARM_SERVICE);
		
		String username = settings.getString(Supermanager.PREFS_USERNAME, null);
   		String password = settings.getString(Supermanager.PREFS_PASSWORD, null);
   		
   		// supermanager sync intent
		SupermanagerIntent superIntent = 
			new SupermanagerIntent(SupermanagerIntent.ACTION_VIEW,
					Supermanager.Home.CONTENT_URI, service, null);
		superIntent.putExtra("cat.joronya.supermanager.login.username", username);
		superIntent.putExtra("cat.joronya.supermanager.login.password", password);
		
		// creem el pending intent
		PendingIntent newPending =  PendingIntent.getService(service, 0, superIntent, 0);
		
		// primer mirem de cancelar per si ja teniem 
		alarmManager.cancel(newPending);
		
		// notification hour
   		String notificationHour = settings.getString(Supermanager.PREFS_DUETIME_NOTIFICATION_HOUR, "04");
	   		
   		Cursor cursor = service.getContentResolver().query(
			Supermanager.Home.CONTENT_URI, 
			Supermanager.Home.PROJECTION, 
			Supermanager.Home.DUE_TIME+" > "+(System.currentTimeMillis()/1000), 
			null, 
			Supermanager.Home.DUE_TIME+" DESC");
			
		// hi ha alguna data? Hem arribat al moment de mostrar la notificacio que s'escaigui
		if( cursor.moveToFirst() )
		{
			// duetime - notificationHour
			long duetime = cursor.getInt(4);
			duetime -= (Integer.parseInt(notificationHour)*60*60);
				
			// programem l'alarma al duetime - hores abans
			alarmManager.set(AlarmManager.RTC_WAKEUP, duetime*1000, newPending);
				
			Log.d(TAG, "LoginSync: notification alarm scheduled");
		}

		Log.d(TAG, "LoginSync: duetime notification scheduled!");		
	}

}	
